/*
 * $Id: ChangeSpecDialog.java 45 2002-10-27 14:15:24Z bpruessmann $
 *
 * Copyright (c) 2001 Boris Pruessmann and others.
 * All rights reserved.   This program and the accompanying materials
 * are made available under the terms of the Common Public License v0.5
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/cpl-v05.html
 * 
 * Contributors:
 *    Boris Pruessmann - Initial implementation.
 */
package net.sourceforge.perforce.ui.dialogs;


import java.util.ArrayList;
import java.util.List;

import net.sourceforge.perforce.api.internal.Spec;
import net.sourceforge.perforce.api.internal.SpecData;
import net.sourceforge.perforce.core.PerforceException;
import net.sourceforge.perforce.core.api.IChangeResult;
import net.sourceforge.perforce.core.api.IPerforceServer;
import net.sourceforge.perforce.core.resources.IChangelist;
import net.sourceforge.perforce.ui.internal.Policy;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.viewers.ColumnWeightData;
import org.eclipse.jface.viewers.TableLayout;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.Text;


/**
  * @version 	$Revision: 45 $
  * @author		<a href="mailto:bpruessmann@users.sourceforge.net">Boris Pruessmann</a>
  */
public class ChangeSpecDialog extends Dialog
{
	// --------------------------------------------------------------------------- Private Constants
	
	private static final int WIDTH_HINT = 450;
	private static final int HEIGHT_HINT = 100;

	// --------------------------------------------------------------------------- Private Variables

	private Text descriptionText;
	private Text filesText;	
	private TableViewer viewer;
	private boolean readOnly;
	
	private Spec spec;
	private SpecData specData;

	// --------------------------------------------------------------- Public Static Factory Methods

	public static final ChangeSpecDialog newInstance(Shell parentShell, IPerforceServer server)
		throws PerforceException
	{		
		ChangeSpecDialog result = new ChangeSpecDialog(parentShell);

		IChangeResult changeResult = server.change((Integer) null);	
		result.specData = changeResult.getChangeSpecData();
		result.spec = changeResult.getChangeSpecDefinition();

		return result;
	}
	
	public static final ChangeSpecDialog newInstance(Shell parentShell, IChangelist changelist)
		throws PerforceException
	{
		ChangeSpecDialog result = new ChangeSpecDialog(parentShell);
		
		IChangeResult changeResult = changelist.getServer().change(changelist.getId());	
		result.specData = changeResult.getChangeSpecData();
		result.spec = changeResult.getChangeSpecDefinition();

		return result;
	}
	
	// -------------------------------------------------------------------------------- Constructors
	
	/** @see Dialog#Dialog(org.eclipse.swt.widgets.Shell) */
	ChangeSpecDialog(Shell parentShell)
	{
		super(parentShell);
	}
	
	// ------------------------------------------------------------------------------ Public Methods
		
	public void setReadOnly(boolean readOnly)
	{
		this.readOnly = readOnly;
	}
	
	public boolean isReadOnly()
	{
		return readOnly;
	}
	
	// --------------------------------------------------------------------------- Protected Methods
	
	/** @see Dialog#createDialogArea(Composite) */
	protected Control createDialogArea(Composite parent)
	{
		getShell().setText(Policy.bind("ChangeSpecDialog.dialogTitle"));                //NON-NLS-1$
		
		Composite composite = new Composite(parent, SWT.NULL);
		GridLayout layout = new GridLayout();
		layout.numColumns = 2;
		composite.setLayout(layout);
		composite.setLayoutData(new GridData(GridData.FILL_BOTH));
		
		createLabel(composite, Policy.bind("ChangeSpecDialog.change"));	               //$NON-NLS-1$
		createText(composite, getChangelist());

		createLabel(composite, Policy.bind("ChangeSpecDialog.date"));                  //$NON-NLS-1$
		createText(composite, getDate());

		createLabel(composite, Policy.bind("ChangeSpecDialog.client"));                //$NON-NLS-1$
		createText(composite, getClientName());
		
		createLabel(composite, Policy.bind("ChangeSpecDialog.user"));                  //$NON-NLS-1$
		createText(composite, getUserName());
		
		createLabel(composite, Policy.bind("ChangeSpecDialog.status"));                //$NON-NLS-1$
		createText(composite, getStatus());
		
		Label descriptionLabel = 
			createLabel(composite, Policy.bind("ChangeSpecDialog.description"));       //$NON-NLS-1$
		GridData data = new GridData(GridData.FILL_BOTH);
		data.horizontalSpan = 2;
		descriptionLabel.setLayoutData(data);
		
		int style = SWT.BORDER | SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL;
		if (readOnly == true)
		{
			style |= SWT.READ_ONLY;
		}
			
		descriptionText = new Text(composite, style);
		descriptionText.addKeyListener(new KeyAdapter() 
		{
			public void keyPressed(KeyEvent e) 
			{
				String description = descriptionText.getText();
				if (description.equals("<enter description here>"))
				{
					getButton(IDialogConstants.OK_ID).setEnabled(false);
				}
				else
				{
					getButton(IDialogConstants.OK_ID).setEnabled(true);					
				}
			}
		});
		
		data = new GridData(GridData.FILL_BOTH);
		data.horizontalSpan = 2;
		data.widthHint = WIDTH_HINT;
		data.heightHint = HEIGHT_HINT;
		descriptionText.setLayoutData(data);
		descriptionText.setText(getDescription());
		
		descriptionText.selectAll();
		descriptionText.setFocus();
		
		Label filesLabel =
			createLabel(composite, Policy.bind("ChangeSpecDialog.files"));             //$NON-NLS-1$
		data = new GridData(GridData.FILL_BOTH);
		data.horizontalSpan = 2;
		filesLabel.setLayoutData(data);
		
		createTable(composite);
		viewer.add(getFiles());
		
		TableItem[] items = viewer.getTable().getItems();
		for (int i = 0, length = items.length; i < length; i++)
		{
			items[i].setChecked(true);
		}

		return composite;		
	}
	
	/** @see org.eclipse.jface.dialogs.Dialog#createButtonBar(Composite) */
	protected Control createButtonBar(Composite parent) 
	{
		Control result = super.createButtonBar(parent);

		String description = descriptionText.getText();
		if (description.equals("<enter description here>"))
		{
			getButton(IDialogConstants.OK_ID).setEnabled(false);
		}
		else
		{
			getButton(IDialogConstants.OK_ID).setEnabled(true);					
		}
		
		return result;
	}
	
	/** @see Dialog#okPressed() */
	protected void okPressed() 
	{
		specData.replace("Description", descriptionText.getText());                    //$NON-NLS-1$
	
		List files = new ArrayList();
		TableItem[] items = viewer.getTable().getItems();
		for (int i = 0, length = items.length; i < length; i++)
		{
			if (items[i].getChecked())
			{
				files.add(items[i].getText());
			}
		}
		
		for (int i = 0, length = files.size(); i < length; i++)
		{
			specData.replace("Files" + i, (String) files.get(i));                      //$NON-NLS-1$
		}
		
		for (int i = files.size(), length = items.length; i < length; i++)
		{
			specData.replace("Files" + i, "");                                         //$NON-NLS-1$
		}
		
		super.okPressed();
	}

	// ----------------------------------------------------------------------------- Private Methods

	private void createTable(Composite composite) 
	{	
		int style = SWT.BORDER | SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL;
		style |= SWT.CHECK;

		Table table = new Table(composite, style);		
		
		TableLayout layout = new TableLayout();
		layout.addColumnData(new ColumnWeightData(1));
		
		table.setLayout(layout);
		table.setLinesVisible(true);
		
		viewer = new TableViewer(table);
		
		GridData data = new GridData(GridData.FILL_BOTH);
		data.horizontalSpan = 2;
		data.widthHint = WIDTH_HINT;
		data.heightHint = HEIGHT_HINT;

		table.setLayoutData(data);
	}
	
	private Label createLabel(Composite composite, String text)
	{
		Label result = new Label(composite, SWT.NULL);
		result.setLayoutData(new GridData());
		result.setText(text);		
		
		return result;
	}

	private Text createText(Composite composite, String text)
	{	
		Text result = new Text(composite, SWT.READ_ONLY);
		GridData data = new GridData(GridData.HORIZONTAL_ALIGN_END);
		result.setLayoutData(data);
		result.setText(text);
		
		return result;
	}

	private String getChangelist()
	{
		return specData.get("Change");                                                //$NON-NLS-1$
	}	

	private String getDate()
	{
		return specData.get("Date");                                                  //$NON-NLS-1$	
	}

	private String getClientName()
	{
		return specData.get("Client");                                                //$NON-NLS-1$
	}	
	
	private String getUserName()
	{
		return specData.get("User");                                                  //$NON-NLS-1$
	}	

	private String getStatus()
	{
		return specData.get("Status");                                                //$NON-NLS-1$
	}	
	
	private String[] getFiles()
	{
		List files = new ArrayList();

		int i = 0;
		boolean hasMore = true;
		do
		{
			String filename = specData.get("Files" + i++);                             //$NON-NLS-1$
			if ("".equals(filename))                                                   //$NON-NLS-1$
			{
				hasMore = false;
			}
			else
			{
				files.add(filename);
			}
		}
		while (hasMore);
		
		return (String[]) files.toArray(new String[files.size()]);
	}

	public String getDescription()
	{
		return specData.get("Description").trim();                                    //$NON-NLS-1$
	}
	
	public String getChangeSpecString()
	{
		return spec.format(specData);
	}
}
